package com.runjian.rundo.iot.agent.common.network.tcp.client;

import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;

import com.runjian.rundo.iot.agent.common.codec.DeviceMessageCodec;
import com.runjian.rundo.iot.agent.common.network.core.cache.TcpNetworkClientCache;
import com.runjian.rundo.iot.agent.common.network.tcp.client.config.TcpNetworkClientConfiguration;
import com.runjian.rundo.iot.agent.common.network.tcp.client.handle.TcpClientMessageHandler;
import com.runjian.rundo.iot.agent.common.network.tcp.client.session.TcpClientDeviceSessionManager;
import com.runjian.rundo.iot.agent.common.network.tcp.handle.TcpIdleEventHandler;
import com.runjian.rundo.iot.agent.common.network.tcp.parser.PayloadParser;
import com.runjian.rundo.iot.agent.common.thread.ScheduledExecutorFactory;

import cn.hutool.core.util.ObjectUtil;
import io.netty.channel.Channel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * Tcp 客户端管理器
 *
 * @author CaoQingHua
 */
@Slf4j
@Getter
@Setter
@RequiredArgsConstructor
public class TcpNetworkClientManager implements ApplicationRunner {

    private final ScheduledExecutorFactory taskScheduledExecutorFactory;

    private final TcpNetworkClientConfiguration tcpNetworkClientProperties;

    private final TcpClientDeviceSessionManager sessionManager;

    private final TcpIdleEventHandler idleEventHandler;

    private final DeviceMessageCodec codec;

    private final PayloadParser payloadParser;

    private final TcpClientMessageHandler messageHandler;

    private final TcpNetworkClientCache tcpNetworkClientCache;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 开始方法
        if (ObjectUtil.isNull(this.tcpNetworkClientProperties) || ObjectUtil.isEmpty(this.tcpNetworkClientProperties.getList())) {
            log.info("Tcp 客户端网络配置为空,没有要启动的客户端网络");
        }
        // 定时任务
        taskScheduledExecutorFactory.addScheduleAtFixedRate(this::startConnection, 0,
            tcpNetworkClientProperties.getCheckConnectStatusInterval(), TimeUnit.SECONDS);
    }

    /**
     * 开始连接,需要提交定时任务，定时检测连接状态，如果连接状态为断开
     */
    public void startConnection() {
        try {
            // 连接回调函数
            this.tcpNetworkClientProperties.getList().forEach(e -> {
                TcpNetworkClient client = tcpNetworkClientCache.getTcpNetworkClientMap().computeIfAbsent(e.getId(), id -> {
                    TcpNetworkClient tcpNetworkClient =
                        new TcpNetworkClient(e, sessionManager, idleEventHandler, codec, payloadParser, messageHandler);
                    tcpNetworkClient.initial();
                    return tcpNetworkClient;
                });
                if (Boolean.FALSE.equals(client.status())) {
                    if (log.isDebugEnabled()) {
                        log.debug("Tcp未连接，现在开始连接,IP:({}/{})", e.getHost(), e.getPort());
                    }
                    client.channelConnection();
                }
            });
        } catch (Exception e) {
            log.error("Tcp连接异常,", e);
        }
    }

}
